"""
枚举字典
"""
from typing import List

from fastapi import APIRouter, Query

from app.common.common import DbDep, AuditLogDep
from app.crud.enum_crud import (
	get_enum_map_by_types,
	create_enum_item,
	update_enum_item,
	delete_enum_item,
	get_all_enum_types,
)
from app.schemas.enum_schemas import EnumItemCreate, EnumItemUpdate, EnumItemOut
from common.exceptions import BizException, ErrorCode
from common.logger import create_logger
from common.redis import get_redis_service
from common.response import ApiResponse

logger = create_logger(__name__)
router = APIRouter(prefix="/enums", tags=["枚举管理"])

# 缓存键常量
FULL_ENUMS_CACHE_KEY = "enums:full_data"
# 缓存过期时间（秒） - 1小时
FULL_ENUMS_CACHE_TTL = 7200


@router.get("/full", summary="获取全量枚举信息(带缓存)")
async def get_full_enums(
		db: DbDep,
		refresh_cache: bool = Query(False, description="是否刷新缓存，默认为False")
):
	"""
	获取全量枚举信息并缓存

	优先从缓存获取，如果缓存不存在/已过期或指定刷新缓存，则查询数据库获取所有枚举类型
	并调用get_enum_map_by_types获取全量枚举字典数据，保存到缓存后返回

	Args:
		refresh_cache: 是否刷新缓存，为True时直接查询数据库并更新缓存

	Returns:
		全量枚举映射字典
	"""

	# 获取Redis服务
	redis_service = get_redis_service()

	# 如果不需要刷新缓存，则尝试从缓存获取
	if not refresh_cache:
		cached_data = redis_service.get(FULL_ENUMS_CACHE_KEY)
		if cached_data:
			logger.debug("全量枚举数据从缓存中获取成功")
			return ApiResponse(data=cached_data)
	else:
		logger.debug("接收到刷新缓存请求，将直接查询数据库并更新缓存")

	try:
		# 获取所有枚举类型
		enum_types = await get_all_enum_types(db)
		if not enum_types:
			logger.warning("未找到任何枚举类型")
			return ApiResponse(data={})

		# 获取全量枚举字典数据
		logger.debug(f"开始获取全量枚举数据，类型数量: {len(enum_types)}")
		enums_map = await get_enum_map_by_types(db, enum_types)

		# 保存到缓存
		if enums_map and redis_service.is_available():
			# 将EnumMap对象转换为可JSON序列化的Python字典
			serializable_data = {}
			for type_name, enum_items in enums_map.items():
				serializable_data[type_name] = [
					item.model_dump() for item in enum_items
				]

			cache_result = redis_service.set(
				FULL_ENUMS_CACHE_KEY,
				serializable_data,
				ex=FULL_ENUMS_CACHE_TTL
			)
			if cache_result:
				logger.debug("全量枚举数据已成功缓存")
			else:
				logger.warning("全量枚举数据缓存失败")

		logger.debug("全量枚举数据从数据库获取成功")
		return ApiResponse(data=enums_map)
	except Exception as e:
		logger.error(f"获取全量枚举数据失败: {str(e)}")
		raise BizException(ErrorCode.GONE, "获取全量枚举数据失败")


@router.get("", summary="批量获取枚举条目")
async def get_enums(
		db: DbDep,
		audit_log: AuditLogDep,
		type_names: List[str] = Query(..., description="枚举类型名称列表"),
):
	"""
	批量获取枚举条目

	Args:
		type_names: 枚举类型名称列表

	Returns:
		枚举映射字典
	"""
	audit_log.record("查询枚举列表", f"类型: {type_names}")
	enums_map = await get_enum_map_by_types(db, type_names)
	return ApiResponse(data=enums_map)


@router.post("", summary="新增枚举条目", response_model=ApiResponse[EnumItemOut])
async def add_enum_item(
		db: DbDep,
		_audit: AuditLogDep,
		body: EnumItemCreate
) -> ApiResponse[EnumItemOut]:
	"""同 type 下 value 已存在会抛 409"""
	item = await create_enum_item(db, body)
	return ApiResponse.success(EnumItemOut.model_validate(item))


@router.put("/{item_id}", summary="修改枚举条目", response_model=ApiResponse[EnumItemOut])
async def edit_enum_item(
		db: DbDep,
		_audit: AuditLogDep,
		item_id: int,
		body: EnumItemUpdate
) -> ApiResponse[EnumItemOut]:
	item = await update_enum_item(db, item_id, body)
	if not item:
		raise BizException.from_error_code(ErrorCode.ENUM_ITEM_NOT_FOUND)
	return ApiResponse.success(EnumItemOut.model_validate(item))


@router.delete("/{item_id}", summary="删除枚举条目")
async def remove_enum_item(
		db: DbDep,
		_audit: AuditLogDep,
		item_id: int
) -> ApiResponse[dict]:
	ok = await delete_enum_item(db, item_id)
	if not ok:
		raise BizException.from_error_code(ErrorCode.ENUM_ITEM_NOT_FOUND)
	return ApiResponse.success(message="删除成功")
